package com.google.code.roledroid;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.util.Log;

/**
 * The Class CharacterDBHelper is a class that provides access and tools for 
 * the Underlying Character SQLite database. 
 */
public class CharacterDBHelper {
	
	/**
	 * The Class Row is used as a return type.
	 * It contains all the information of a single database row, that
	 * is, a single character information.
	 */
	class Row extends Object {
		
		/** The unique id of that row. */
		public long _Id;        
		
		/** The field name of the character. */
		public String name;        
	}

	/** The Constant DATABASE_CREATE is a SQL command used to create a table. */
	private static final String DATABASE_CREATE =
			"create table CHARDATA(_id integer primary key autoincrement, "            
					+ "name text not null"
					+");";

	/** The Constant DATABASE_NAME. */
	private static final String DATABASE_NAME = "ROLEDB";

	/** The Constant DATABASE_TABLE. */
	private static final String DATABASE_TABLE = "CHARDATA";

	/** The Constant DATABASE_COLUMN_NAMES. */
	private static final String[] DATABASE_COLUMN_NAMES = new String[] {"_id", "name"};;	

	/** The db is the actual dataBase instance. */
	private SQLiteDatabase db;

	/**
	 * Instantiates a new character db helper.
	 *
	 * @param ctx 
	 * 			the android context, used to avoid the re-initialization of the 
	 * 			database if that is already present in the context.
	 */
	public CharacterDBHelper(Context ctx) {
		try {   
			boolean init = false;
			if(!ctx.getDatabasePath(DATABASE_NAME).exists())
				init = true;        	
			db = ctx.openOrCreateDatabase(DATABASE_NAME, android.content.Context.MODE_PRIVATE, null);
			if( init )
				db.execSQL(DATABASE_CREATE);
		} catch (SQLiteException e) {
			db = null;            
		}
	}

	/**
	 * Close closes the DataBase.
	 */
	public void close() {
		db.close();
	}

	/**
	 * This method Creates a new row and inserts it into the db.
	 *
	 * @param name the name for the character to insert.
	 * @return the long that the insert method returns. 
	 * 			It represents the id of the inserted row, or -1 if something went wrong. 
	 */
	public long createRow(String name) {
		ContentValues initialValues = new ContentValues();		
		initialValues.put("name", name);
		return db.insert(DATABASE_TABLE, null, initialValues);
	}

	/**
	 * Delete a row with the given id.
	 *
	 * @param rowId the id of the row to delete.
	 * @return the int returned should be always 1. 
	 * It's the output of the deletion operation of teh db, it returns the number of rows 
	 * affected, and if the rowId parameter is valid, taht should return 1.
	 */
	public int deleteRow(long rowId) {
		return db.delete(DATABASE_TABLE, "_id=" + rowId, null);
	}

	/**
	 * Fetch all rows.
	 *
	 * @return the list of all rows stored in the database.
	 */
	public List<Row> fetchAllRows() {
		ArrayList<Row> ret = new ArrayList<Row>();
		try {
			Cursor c =
					db.query(DATABASE_TABLE, DATABASE_COLUMN_NAMES, 
							null, null, null, null, null);
			int numRows = c.getCount();
			c.moveToFirst();
			for (int i = 0; i < numRows; ++i) {
				Row row = new Row();
				row._Id = c.getLong(0);				
				row.name = c.getString(1);
				ret.add(row);
				c.moveToNext();
			}
		} catch (SQLException e) {
			Log.e("Exception on query", e.toString());
		}
		return ret;
	}

	/**
	 * Fetch a single row.
	 *
	 * @param rowId the row id
	 * @return the row
	 */
	public Row fetchRow(long rowId) {
		Row row = new Row();		
		Cursor c =
				db.query(true, DATABASE_TABLE, DATABASE_COLUMN_NAMES, "_id=" + rowId, 
						null, null,
						null, null, null);
		if (c.getCount() > 0) {
			c.moveToFirst();
			row._Id = c.getLong(0);			
			row.name = c.getString(1);
			return row;
		} else {
			row._Id = -1;
			row.name= null;
		}
		return row;
	}

	/**
	 * Update a row.
	 *
	 * @param rowId the row id
	 * @param name the new content of the field name
	 * @return the number of rows affected (should be 1 if all is ok)
	 */
	public int updateRow(long rowId, String name) {
		ContentValues args = new ContentValues();		
		args.put("name", name);
		return db.update(DATABASE_TABLE, args, "_id=" + rowId, null);
	}
	
	/**
	 * Gets the all rows but not as a list, but as a cursor (much more convenient).
	 *
	 * @return the cursos to access all rows. It's positioned before the first entry.
	 */
	public Cursor getAllRows() {
		try {
			return db.query(DATABASE_TABLE, DATABASE_COLUMN_NAMES, 
					null, null, null, null, null);
		} catch (SQLException e) {
			Log.e("Exception on query", e.toString());
			return null;
		}
	}
	
	/**
	 * Gets a whole character table column.
	 *
	 * @param column_name the name of the desired column to retrieve
	 * @return the column contents as a List of strings
	 */
	public List<String> getColumn(String column_name) {		
	    Cursor c = db.query(DATABASE_TABLE, DATABASE_COLUMN_NAMES, 
	    		null, null, null, null,
	        null);	    
	    List<String> res = new ArrayList<String>();
	    int idx = c.getColumnIndex(column_name);

	    for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
	        res.add(c.getString(idx));
	    }
	    return res;		
	}
}
